//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package project_member_api_serv

import (
	"context"
	"fmt"
	"time"

	"atomgit.com/openlinksaas-org/api-server/api_common"
	"atomgit.com/openlinksaas-org/api-server/dao"
	"atomgit.com/openlinksaas-org/api-server/dao/project_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/user_dao"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/events/events_project"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/events_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_member_api"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
	"google.golang.org/protobuf/types/known/anypb"
)

func (apiImpl *ProjectMemberApiImpl) addGenInviteEvent(
	sessionItem *dao.SessionDbItem,
	req *project_member_api.GenInviteRequest,
	projectItem *project_dao.ProjectInfoDbItem) {
	eventTime := time.Now().UnixNano() / 1e6
	eventData, err := anypb.New(&events_project.GenInviteEvent{})
	if err != nil {
		fmt.Println(err)
		return
	}
	dbSess, err := dao.StartSession()
	if err != nil {
		return
	}
	defer dao.EndSession(dbSess)
	dbSess.WithTransaction(context.Background(), func(sessCtx mongo.SessionContext) (interface{}, error) {
		err := api_common.AddEvent(sessCtx, &events_api.Event{
			EventId:         uuid.NewString(),
			UserId:          sessionItem.UserId,
			UserDisplayName: sessionItem.DisplayName,
			ProjectId:       req.ProjectId,
			ProjectName:     projectItem.BasicInfo.ProjectName,
			EventType:       events_api.EVENT_TYPE_EVENT_TYPE_PROJECT,
			EventTime:       eventTime,
			RefType:         events_api.EVENT_REF_TYPE_EVENT_REF_TYPE_PROJECT,
			RefId:           req.ProjectId,
			EventData:       eventData,
		}, false, "", "")
		if err != nil {
			fmt.Println(err)
		}
		return nil, err
	})
}

func (apiImpl *ProjectMemberApiImpl) addJoinEvent(
	sessionItem *dao.SessionDbItem,
	req *project_member_api.JoinRequest,
	projectItem *project_dao.ProjectInfoDbItem) {
	eventTime := time.Now().UnixNano() / 1e6
	eventData, err := anypb.New(&events_project.JoinProjectEvent{})
	if err != nil {
		fmt.Println(err)
		return
	}
	dbSess, err := dao.StartSession()
	if err != nil {
		return
	}
	defer dao.EndSession(dbSess)
	dbSess.WithTransaction(context.Background(), func(sessCtx mongo.SessionContext) (interface{}, error) {
		err := api_common.AddEvent(sessCtx, &events_api.Event{
			EventId:         uuid.NewString(),
			UserId:          sessionItem.UserId,
			UserDisplayName: sessionItem.DisplayName,
			ProjectId:       projectItem.ProjectId,
			ProjectName:     projectItem.BasicInfo.ProjectName,
			EventType:       events_api.EVENT_TYPE_EVENT_TYPE_PROJECT,
			EventTime:       eventTime,
			RefType:         events_api.EVENT_REF_TYPE_EVENT_REF_TYPE_PROJECT,
			RefId:           projectItem.ProjectId,
			EventData:       eventData,
		}, false, "", "")
		if err != nil {
			fmt.Println(err)
		}
		return nil, err
	})

}

func (apiImpl *ProjectMemberApiImpl) addLeaveEvent(
	sessionItem *dao.SessionDbItem,
	req *project_member_api.LeaveRequest,
	projectItem *project_dao.ProjectInfoDbItem) {
	eventTime := time.Now().UnixNano() / 1e6
	eventData, err := anypb.New(&events_project.LeaveProjectEvent{})
	if err != nil {
		fmt.Println(err)
		return
	}
	dbSess, err := dao.StartSession()
	if err != nil {
		return
	}
	defer dao.EndSession(dbSess)
	dbSess.WithTransaction(context.Background(), func(sessCtx mongo.SessionContext) (interface{}, error) {
		err := api_common.AddEvent(sessCtx, &events_api.Event{
			EventId:         uuid.NewString(),
			UserId:          sessionItem.UserId,
			UserDisplayName: sessionItem.DisplayName,
			ProjectId:       req.ProjectId,
			ProjectName:     projectItem.BasicInfo.ProjectName,
			EventType:       events_api.EVENT_TYPE_EVENT_TYPE_PROJECT,
			EventTime:       eventTime,
			RefType:         events_api.EVENT_REF_TYPE_EVENT_REF_TYPE_PROJECT,
			RefId:           req.ProjectId,
			EventData:       eventData,
		}, false, "", "")
		if err != nil {
			fmt.Println(err)
		}
		return nil, err
	})
}

func (apiImpl *ProjectMemberApiImpl) addRemoveMemberEvent(
	sessionItem *dao.SessionDbItem,
	req *project_member_api.RemoveMemberRequest,
	projectItem *project_dao.ProjectInfoDbItem,
	userItem *user_dao.UserInfoDbItem) {
	eventTime := time.Now().UnixNano() / 1e6
	eventData, err := anypb.New(&events_project.RemoveProjectMemberEvent{
		MemberUserId:      req.MemberUserId,
		MemberDisplayName: userItem.BasicInfo.DisplayName,
	})
	if err != nil {
		fmt.Println(err)
		return
	}
	dbSess, err := dao.StartSession()
	if err != nil {
		return
	}
	defer dao.EndSession(dbSess)
	dbSess.WithTransaction(context.Background(), func(sessCtx mongo.SessionContext) (interface{}, error) {
		err := api_common.AddEvent(sessCtx, &events_api.Event{
			EventId:         uuid.NewString(),
			UserId:          sessionItem.UserId,
			UserDisplayName: sessionItem.DisplayName,
			ProjectId:       req.ProjectId,
			ProjectName:     projectItem.BasicInfo.ProjectName,
			EventType:       events_api.EVENT_TYPE_EVENT_TYPE_PROJECT,
			EventTime:       eventTime,
			RefType:         events_api.EVENT_REF_TYPE_EVENT_REF_TYPE_PROJECT,
			RefId:           req.ProjectId,
			EventData:       eventData,
		}, false, "", "")
		if err != nil {
			fmt.Println(err)
		}
		return nil, err
	})

}

func (apiImpl *ProjectMemberApiImpl) addCreateRoleEvent(
	sessionItem *dao.SessionDbItem,
	req *project_member_api.CreateRoleRequest,
	projectItem *project_dao.ProjectInfoDbItem,
	roleId string, nowTime int64) {
	eventData, err := anypb.New(&events_project.CreateRoleEvent{
		RoleId:   roleId,
		RoleName: req.BasicInfo.RoleName,
	})
	if err != nil {
		fmt.Println(err)
		return
	}
	dbSess, err := dao.StartSession()
	if err != nil {
		return
	}
	defer dao.EndSession(dbSess)
	dbSess.WithTransaction(context.Background(), func(sessCtx mongo.SessionContext) (interface{}, error) {
		err := api_common.AddEvent(sessCtx, &events_api.Event{
			EventId:         uuid.NewString(),
			UserId:          sessionItem.UserId,
			UserDisplayName: sessionItem.DisplayName,
			ProjectId:       req.ProjectId,
			ProjectName:     projectItem.BasicInfo.ProjectName,
			EventType:       events_api.EVENT_TYPE_EVENT_TYPE_PROJECT,
			EventTime:       nowTime,
			RefType:         events_api.EVENT_REF_TYPE_EVENT_REF_TYPE_PROJECT,
			RefId:           req.ProjectId,
			EventData:       eventData,
		}, false, "", "")
		if err != nil {
			fmt.Println(err)
		}
		return nil, err
	})

}

func (apiImpl *ProjectMemberApiImpl) addUpdateRoleEvent(
	sessionItem *dao.SessionDbItem,
	req *project_member_api.UpdateRoleRequest,
	projectItem *project_dao.ProjectInfoDbItem,
	roleItem *project_dao.RoleInfoDbItem) {
	eventTime := time.Now().UnixNano() / 1e6
	eventData, err := anypb.New(&events_project.UpdateRoleEvent{
		RoleId:      req.RoleId,
		OldRoleName: roleItem.BasicInfo.RoleName,
		NewRoleName: req.BasicInfo.RoleName,
	})
	if err != nil {
		fmt.Println(err)
		return
	}
	dbSess, err := dao.StartSession()
	if err != nil {
		return
	}
	defer dao.EndSession(dbSess)
	dbSess.WithTransaction(context.Background(), func(sessCtx mongo.SessionContext) (interface{}, error) {
		err := api_common.AddEvent(sessCtx, &events_api.Event{
			EventId:         uuid.NewString(),
			UserId:          sessionItem.UserId,
			UserDisplayName: sessionItem.DisplayName,
			ProjectId:       req.ProjectId,
			ProjectName:     projectItem.BasicInfo.ProjectName,
			EventType:       events_api.EVENT_TYPE_EVENT_TYPE_PROJECT,
			EventTime:       eventTime,
			RefType:         events_api.EVENT_REF_TYPE_EVENT_REF_TYPE_PROJECT,
			RefId:           req.ProjectId,
			EventData:       eventData,
		}, false, "", "")
		if err != nil {
			fmt.Println(err)
		}
		return nil, err
	})

}

func (apiImpl *ProjectMemberApiImpl) addRemoveRoleEvent(
	sessionItem *dao.SessionDbItem,
	req *project_member_api.RemoveRoleRequest,
	projectItem *project_dao.ProjectInfoDbItem,
	roleItem *project_dao.RoleInfoDbItem) {
	//add event
	eventTime := time.Now().UnixNano() / 1e6
	eventData, err := anypb.New(&events_project.RemoveRoleEvent{
		RoleId:   req.RoleId,
		RoleName: roleItem.BasicInfo.RoleName,
	})
	if err != nil {
		fmt.Println(err)
		return
	}
	dbSess, err := dao.StartSession()
	if err != nil {
		return
	}
	defer dao.EndSession(dbSess)
	dbSess.WithTransaction(context.Background(), func(sessCtx mongo.SessionContext) (interface{}, error) {
		err := api_common.AddEvent(sessCtx, &events_api.Event{
			EventId:         uuid.NewString(),
			UserId:          sessionItem.UserId,
			UserDisplayName: sessionItem.DisplayName,
			ProjectId:       req.ProjectId,
			ProjectName:     projectItem.BasicInfo.ProjectName,
			EventType:       events_api.EVENT_TYPE_EVENT_TYPE_PROJECT,
			EventTime:       eventTime,
			RefType:         events_api.EVENT_REF_TYPE_EVENT_REF_TYPE_PROJECT,
			RefId:           req.ProjectId,
			EventData:       eventData,
		}, false, "", "")
		if err != nil {
			fmt.Println(err)
		}
		return nil, err
	})

}

func (apiImpl *ProjectMemberApiImpl) addSetMemberRoleEvent(
	sessionItem *dao.SessionDbItem,
	req *project_member_api.SetMemberRoleRequest,
	projectItem *project_dao.ProjectInfoDbItem,
	roleItem *project_dao.RoleInfoDbItem,
	userItem *user_dao.UserInfoDbItem) {
	eventTime := time.Now().UnixNano() / 1e6
	eventData, err := anypb.New(&events_project.SetProjectMemberRoleEvent{
		RoleId:            req.RoleId,
		RoleName:          roleItem.BasicInfo.RoleName,
		MemberUserId:      req.MemberUserId,
		MemberDisplayName: userItem.BasicInfo.DisplayName,
	})
	if err != nil {
		fmt.Println(err)
		return
	}
	dbSess, err := dao.StartSession()
	if err != nil {
		return
	}
	defer dao.EndSession(dbSess)
	dbSess.WithTransaction(context.Background(), func(sessCtx mongo.SessionContext) (interface{}, error) {
		err := api_common.AddEvent(sessCtx, &events_api.Event{
			EventId:         uuid.NewString(),
			UserId:          sessionItem.UserId,
			UserDisplayName: sessionItem.DisplayName,
			ProjectId:       req.ProjectId,
			ProjectName:     projectItem.BasicInfo.ProjectName,
			EventType:       events_api.EVENT_TYPE_EVENT_TYPE_PROJECT,
			EventTime:       eventTime,
			RefType:         events_api.EVENT_REF_TYPE_EVENT_REF_TYPE_PROJECT,
			RefId:           req.ProjectId,
			EventData:       eventData,
		}, false, "", "")
		if err != nil {
			fmt.Println(err)
		}
		return nil, err
	})

}
